<?php declare(strict_types=1);


namespace App\Controller;

use App\Common\Response;
use App\Data\EventData;
use App\Exception\LogicException;
use App\Middleware\AuthMiddleware;
use App\Middleware\EncryptionMiddleware;
use App\Model\Event;
use App\Model\EventInfo;
use App\Service\EventService;
use App\Service\FileService;
use Hyperf\Di\Annotation\Inject;
use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\Middleware;
use Hyperf\HttpServer\Annotation\Middlewares;
use Hyperf\HttpServer\Annotation\RequestMapping;
use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\HttpServer\Contract\ResponseInterface;
use Swoole\Exception;


/**
 * Class EventController
 * @Controller()
 * @Middlewares({
 *   @Middleware(AuthMiddleware::class),
 *   @Middleware(EncryptionMiddleware::class)
 * })
 */
class EventController extends AbstractController
{

    /**
     * @Inject()
     * @var FileService
     */
    private $fileService;

    /**
     * @Inject()
     * @var EventService
     */
    private $eventService;

    /**
     * @Inject()
     * @var EventData
     */
    private $eventData;
    /**
     * 添加事件
     * @RequestMapping(path="/event",methods="post")
     * @param RequestInterface $request
     * @param ResponseInterface $response
     * @return \Psr\Http\Message\ResponseInterface
     */
    public function addEvent(RequestInterface $request, ResponseInterface $response): \Psr\Http\Message\ResponseInterface
    {
        $user = $this->getUser();
        $params = $this->getParams();
        $params['deathline'] = isset($params['deathline']) ? strtotime($params['deathline']) : 0;
        $params['start_submit_at'] = isset($params['start_submit_at']) ? strtotime($params['start_submit_at']) : 0;
        // 验证是否为管理员

        if((int)$user['is_admin'] !== 1){
            return $response->json(Response::fail('非法操作'));
        }
        try {
            $this->check($params['name'] ?? '', '事件名称不能为空');
            $this->check($params['receiver'] ?? '', '接收老师不能为空');
        } catch (\Exception $e) {
            return $response->json(Response::fail($e->getMessage()));
        }
        if($params['deathline'] <= time()){
            return $response->json(Response::fail('截止时间不能小于当前时间'));
        }
        if($params['deathline'] <= $params['start_submit_at']){
            return $response->json(Response::fail('截止时间必须大于开始时间'));
        }
        // 添加数据
        $model = new Event();
        $model->created_by = $user['nick_name'];
        $model->name = $params['name'];
        $model->receiver = $params['receiver'];
        $model->class = $user['class'];
        $model->deathline = $params['deathline'];
        $model->start_submit_at = $params['start_submit_at'];
        $model->save();
        return $response->json(Response::success($model->name,'创建成功'));
    }

    /**
     * 事件删除
     * @RequestMapping(path="/event/del",methods="post")
     * @return \Psr\Http\Message\ResponseInterface
     * @throws \Exception
     */
    public function delEvent(): \Psr\Http\Message\ResponseInterface
    {
        try{
            $params = $this->getParams();
            $this->check($params['event_id'],'event_id为空');
            $this->eventService->del((int)$params['event_id']);
            return $this->response->json(Response::success([],'删除成功',204));
        }catch (LogicException $e){
            return  $this->response->json(Response::fail($e->getMessage()));
        }
    }

    /**
     * 获取用户的能提交的事件列表
     * @RequestMapping(path="/personal/event",methods="get")
     * @return \Psr\Http\Message\ResponseInterface
     */
    public function getStudentEvent(): \Psr\Http\Message\ResponseInterface
    {
        $user = $this->getUser();

        $list = Event::query()
            ->where('deathline','>=', time())
            ->where('start_submit_at', '<=' , time())
            ->where('class', '=', $user['class'])
            ->select(['name','id','receiver','class','deathline','start_submit_at'])
            ->get()->toArray();
        if($list){
            foreach ($list as $index => &$item){
//                $item['id'] = $this->encryptService->publicEncrypt($item['id']);
                $item['deathline'] = $item['deathline'] ? date('Y-m-d H:i:s', $item['deathline']) : '';
                $item['start_submit_at'] = $item['start_submit_at'] ? date('Y-m-d H:i:s', $item['start_submit_at']) : '';
            }
            unset($item);
        }
        return $this->response->json(Response::success($list));
    }

    /**
     * 获取所有事件列表 分页,后台管理员查看
     * @RequestMapping(path="/event",methods="get")
     * @return \Psr\Http\Message\ResponseInterface
     */
    public function eventList(): \Psr\Http\Message\ResponseInterface
    {
        $params = $this->getParams();
        $user = $this->getUser();
        if(!$user['is_admin']){
            return $this->response->json(Response::fail('非法请求'));
        }
        $list = Event::query()->paginate($params['per_page'] ?? 10, ['*'], 'page', $params['page'] ?? 1);
        foreach ($list as $index => $item){
            $list[$index]['deathLine'] = $item['deathline'] ? date('Y-m-d H:i:s', $item['deathline']) : '';
            $list[$index]['startSubmitAt'] = $item['start_submit_at'] ? date('Y-m-d H:i:s', $item['start_submit_at']) : '';
        }
        return $this->response->json(Response::success($list));
    }

    /**
     * 提交作业
     * @RequestMapping(path="/event/submit",methods="post")
     */
    public function submitWork(): \Psr\Http\Message\ResponseInterface
    {

        try{
            $params = $this->getParams();
            $user = $this->getUser();
            $eventModel = Event::query()->where('id', (int)$params['event_id'])->first();

            if(!$eventModel) {
                return $this->response->json(Response::fail('事件不存在'));
            }
            // 检查是否过期
            if($eventModel->start_submit_at > time()){
                return $this->response->json(Response::fail('还没到提交时间'));
            }
            // 检查是否超过提交事件
            if($eventModel->deathline < time()){
                return $this->response->json(Response::fail('超过截止日期，不能提交'));
            }
            $info = EventInfo::query()->where('event_id',$eventModel->id)
                ->where('submitter_id', $user['id'])->count();
            if($info){
                return $this->response->json(Response::fail('已提交过，不能重复提交'));
            }
            $params['file'] = $params['file'] ?? [];
            foreach ($params['file'] as $hash) {
                if($hash) {
                    $fileModel[] = $this->fileService->getTempFile($hash);
                }
            }
            $fileName = '';
            foreach ($fileModel as $model) {
                $fileName .= $model->file_name.',';
            }
            $fileName = rtrim($fileName,',');
            if(!$fileModel) {
                throw new Exception('获取不到资源文件，请确认文件已上传');
            }

            // 插入一条
            $infoModel = new EventInfo();
            $infoModel->event_name = $eventModel->name;
            $infoModel->event_id = $eventModel->id;
            $infoModel->submitter = $user['nick_name'];
            $infoModel->submitter_id = $user['id'];
            $infoModel->file = $fileName;
            $infoModel->remark = $params['remark'] ?? '';


            if($infoModel->save()) {
                // 保存文件
                foreach ($fileModel as $model) {
                    $this->fileService->writeFile($user, $model->hash, $infoModel->id,$eventModel->id);
                }
                return $this->response->json(Response::success($infoModel->toArray(),'成功提交'));
            }
        } catch (Exception $e) {
            return $this->response->json(Response::fail($e->getMessage(), $e->getCode()));
        }

    }

    /**
     * 获取某个事件的提交情况
     * @RequestMapping(path="/event/info",methods="get")
     */
    public function eventInfo(): \Psr\Http\Message\ResponseInterface
    {
        try{
            $params = $this->getParams();
            $info = $this->eventService->eventInfo((int)($params['event_id'] ?? 0));
            $this->eventData->transformDate($info);
            return $this->response->json(Response::success($info));
        } catch (LogicException $e) {
            return $this->response->json(Response::fail($e->getMessage(), $e->getCode()));
        }catch (\Exception $e){
            return $this->response->json(Response::fail('Exception : '.$e->getMessage(), $e->getCode()));
        }

    }
}